package org.noear.quarkus.filter;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;

import java.io.IOException;
import java.util.Map;

/**
 * JAX-RS Web 调用时间统计过滤器
 *
 * @author
 * @since 3.3.0
 */
@Slf4j
@Provider
@Priority(1) // 这个是过滤器执行顺序，越前面执行越早
public class PlusWebInvokeTimeInterceptor implements ContainerRequestFilter, ContainerResponseFilter {

    /**
     * @Inject 注入对象 ，与SpringBoot的对象注入是一样的道理
     */
    @Inject
    StopWatchContext  stopWatchContext;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // 需要主动调用一次，不然生命周期不会触发
        stopWatchContext.init();
        String traceId = stopWatchContext.getTraceId();

        String url = requestContext.getMethod() + " " + requestContext.getUriInfo().getRequestUri();
        // 打印请求参数
        if (isJsonRequest(requestContext)) {
            // 对于 JSON 请求，获取请求体参数（需要特殊处理）
            log.info("[PLUS-{}]start => URL[{}],type[json],params:[{}]",traceId, url, "doParams");
        } else {
            Map<String, String> parameterMap = requestContext.getUriInfo().getQueryParameters().entrySet().stream()
                    .collect(java.util.stream.Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> entry.getValue().toString()
                    ));
            if (MapUtil.isNotEmpty(parameterMap)) {
                String parameters = JSONUtil.toJsonStr(parameterMap);
                log.info("[PLUS-{}]start => URL[{}],type[param],params:[{}]",traceId, url, parameters);
            } else {
                log.info("[PLUS-{}]start => URL[{}],noParams",traceId, url);
            }
        }

    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        StopWatch stopWatch = stopWatchContext.get();
        String traceId = stopWatchContext.getTraceId();
        if (ObjectUtil.isNotNull(stopWatch)) {
            stopWatch.stop();
            log.info("[PLUS-{}]end => URL[{}],useTime:[{}]ms",traceId,
                    requestContext.getMethod() + " " + requestContext.getUriInfo().getRequestUri(),
                    stopWatch.getDuration().toMillis());
        }
    }

    /**
     * 判断本次请求的数据类型是否为json
     *
     * @param requestContext request context
     * @return boolean
     */
    private boolean isJsonRequest(ContainerRequestContext requestContext) {
        String contentType = requestContext.getMediaType() != null ?
                requestContext.getMediaType().toString() : null;
        if (contentType != null) {
            return StringUtils.startsWithIgnoreCase(contentType, "application/json");
        }
        return false;
    }
}